using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using static OpenIddict.Abstractions.OpenIddictConstants;

namespace SageKing.Blazor.OpenIdService;

[Produces("application/json")]
[ApiExplorerSettings(GroupName = "sample-server")]
public class UserinfoController : Controller
{
  private readonly UserManager<AppUser> _userManager;

  public UserinfoController(UserManager<AppUser> userManager)
  {
    _userManager = userManager;
  }

  [Authorize(AuthenticationSchemes = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)]
  [HttpGet("~/connect/userinfo")]
  public async Task<IActionResult> Userinfo()
  {
    var user = await _userManager.GetUserAsync(User);
    if (user is null)
    {
      return Challenge(
        authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
        properties: new AuthenticationProperties(new Dictionary<string, string>
        {
          [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidToken,
          [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
            "The specified access token is bound to an account that no longer exists."
        }));
    }

    var claims = new Dictionary<string, object>(StringComparer.Ordinal)
    {
      // Note: the "sub" claim is a mandatory claim and must be included in the JSON response.
      [Claims.Subject] = await _userManager.GetUserIdAsync(user),
      [Claims.Name] = user.UserName
    };

    if (User.HasScope(Scopes.Email))
    {
      claims[Claims.Email] = await _userManager.GetEmailAsync(user);
      claims[Claims.EmailVerified] = await _userManager.IsEmailConfirmedAsync(user);
    }

    if (User.HasScope(Scopes.Roles))
    {
      claims[Claims.Role] = await _userManager.GetRolesAsync(user);
    }

    // Note: the complete list of standard claims supported by the OpenID Connect specification
    // can be found here: http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims

    return Ok(claims);
  }
}
